﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace IupNET
{

  public enum CallbackRes
  {
    Ignore = -1,
    Default = -2,
    Close = -3,
    Continue = -4
  }

  public class Status
  {

    internal Status(string stat)
    {
      //TODO: maybe we should hook in the macros from c code as tha manual says must be done?
      Control = stat.IndexOf('C') >= 0;
      Shift = stat.IndexOf('S') >= 0;
      Button1 = stat.IndexOf('1') >= 0;
      Button2 = stat.IndexOf('2') >= 0;
      Button3 = stat.IndexOf('3') >= 0;
      Button4 = stat.IndexOf('4') >= 0;
      Button5 = stat.IndexOf('5') >= 0;
    }

    internal Status(bool shift, bool control)
    {
      Shift = shift;
      Control = control;
      Button1 = Button2 = Button3 = Button4 = Button5 = false;
    }

    public override string ToString()
    {
      List<string> strs = new List<string>();
      if (Control) strs.Add("Ctrl");
      if (Shift) strs.Add("Shift");
      if (Button1) strs.Add("Button1");
      if (Button2) strs.Add("Button2");
      if (Button3) strs.Add("Button3");
      if (Button4) strs.Add("Button4");
      if (Button5) strs.Add("Button5");
      return string.Join("+", strs.ToArray());
    }

    public bool Control;
    public bool Shift;
    public bool Button1;
    public bool Button2;
    public bool Button3;
    public bool Button4;
    public bool Button5;
  }

  public class CallbackData
  {
    //TODO: could theese be static??
    public readonly IupBase Sender;
    public string EventName;  //the name of the action generating the event, for example "ACTION", "BUTTON_CB"
    public Control OldTab;
    public Control NewTab;
    public CallbackRes Result;
    public int X;
    public int Y;
    public bool Active;
    public int Value;
    public int[] Values;
    public double Pos;
    public Key Key;
    public Status Status;
    public string Text;
    public double PosX;
    public double PosY;
    public ShowState ShowState;
    public bool DoubleClick;
    public FileDialogStatus FileDialogStatus;



    public CallbackData(IntPtr sender)
    {
      Result = CallbackRes.Default;
      Sender = IupBase.FindObject(sender);
    }

  }

  public delegate void EventCallback(CallbackData e);

  //thoose are the callback delegate definitions, one for each type of callback we support:
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int ActionButtonDelegate(IntPtr sender, int button, int press, int x, int y);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int ActionTextDelegate(IntPtr sender, int ch, string newtext);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int ActionCanvasDelegate(IntPtr sender, float xpos, float ypos);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int ActionToggleDelegate(IntPtr sender, int state);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int ButtonCBDelegate(IntPtr sender, int button, int press, int x, int y);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int SpinCBDelegate(IntPtr sender, int inc);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int MapCBDelegate(IntPtr sender);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int UnMapCBDelegate(IntPtr sender);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int GetFocusCBDelegate(IntPtr sender);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int KillFocusCBDelegate(IntPtr sender);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int EnterWindowCBDelegate(IntPtr sender);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int LeaveWindowCBDelegate(IntPtr sender);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int KAnyCBDelegate(IntPtr sender, int c);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int HelpCBDelegate(IntPtr sender);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int CaretCBDelegate(IntPtr sender, int lin, int col, int pos);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int DropFilesCBDelegate(IntPtr sender, string filename, int num, int x, int y);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int MotionCBDelegate(IntPtr sender, int x, int y, string status);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int FocusCBDelegate(IntPtr sender, int focus);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int KeyPressCBDelegate(IntPtr sender, int c, int press);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int ResizeCBDelegate(IntPtr sender, int width, int height);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int ScrollCBDelegate(IntPtr sender, int op, float posx, float posy);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int WheelCBDelegate(IntPtr sender, float delta, int x, int y, string status);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int ChangeValueCBDelegate(IntPtr sender, double val);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int TabChangeCBDelegate(IntPtr sender, IntPtr new_tab, IntPtr old_tab);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int ActionListDelegate(IntPtr sender, string text, int pos, int state);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int DblClickCBDelegate(IntPtr sender, int pos, string text);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int DropDownCBDelegate(IntPtr sender, int state);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int EditCBDelegate(IntPtr sender, int c, string new_value);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int SelectionCBDelegate(IntPtr sender, int id, int status);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int MultiSelectionCBDelegate(IntPtr sender, IntPtr ids, int n);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int BranchOpenCBDelegate(IntPtr sender, int id);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int BranchCloseCBDelegate(IntPtr sender, int id);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int ExecuteLeafCBDelegate(IntPtr sender, int id);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int RenameNodeCBDelegate(IntPtr sender, int id, string name);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int ShowRenameCBDelegate(IntPtr sender, int id);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int RenameCBDelegate(IntPtr sender, int id, string name);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int DragDropCBDelegate(IntPtr sender, int drag_id, int drop_id, int isshift, int iscontrol);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int RightClickCBDelegate(IntPtr sender, int id);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int CloseCBDelegate(IntPtr sender);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int ShowCBDelegate(IntPtr sender, int state);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int TrayClickCBDelegate(IntPtr sender, int but, int presssed, int dclick);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int FileCBDelegate(IntPtr sender, string filename, string status);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int OpenCBDelegate(IntPtr sender);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int MenuCloseCBDelegate(IntPtr sender);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int ActionItemDelegate(IntPtr sender);
  [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
  delegate int HighlightCBDelegate(IntPtr sender);


  internal class CallbackPair
  {
    internal CallbackPair(EventCallback usercallback, Delegate iupcallback)
    {

      UserCallback = usercallback;
      IupCallback = iupcallback;
    }
    internal readonly EventCallback UserCallback; //this is the users function that will actually be called in the end
    internal readonly Delegate IupCallback;   //we need this only to have garbage collector keep a reference to the delegate
  }


  public class CallbackHandler
  {

    Dictionary<string, CallbackPair> usercallbacks = new Dictionary<string, CallbackPair>();
    IupBase owner;   //the object that owns this handler

    //action events differ for diffrent conrols:





    public CallbackHandler(IupBase owner)
    {
      this.owner = owner;
    }

    string UnDecorateAction(string action)
    {
      //this is a hack to get around the stupid thing that iup calls the event ACTION for several
      //controls but have diffrent protos. for the callbacks
      if (action.StartsWith("ACTION"))
        return "ACTION";
      return action;
    }

    //List<Delegate> deleghandles = new List<Delegate>();
    //List<EventCallback> userhandles = new List<EventCallback>();

    internal void SetCallback(string action, Delegate iupcallback, EventCallback usercallback)
    {
      //deleghandles.Add(iupcallback);
      //userhandles.Add(usercallback);

      Iupc.SetCallback(owner.cobject, UnDecorateAction(action), Marshal.GetFunctionPointerForDelegate(iupcallback));



      usercallbacks[action] = new CallbackPair(usercallback, iupcallback);
    }

    public void Set(string action, EventCallback evt)
    {

      string iupid = UnDecorateAction(action);

      if (evt == null)
      {
        Iupc.SetCallback(owner.cobject, iupid, IntPtr.Zero);
        if (usercallbacks.ContainsKey(action))
          usercallbacks.Remove(action);
      }
      else
      {

        switch (action)
        {
          case "ACTION_BUTTON": SetCallback(action, new ActionButtonDelegate(ActionButton), evt); break;
          case "ACTION_TEXT": SetCallback(action, new ActionTextDelegate(ActionText), evt); break;
          case "ACTION_CANVAS": SetCallback(action, new ActionCanvasDelegate(ActionCanvas), evt); break;
          case "ACTION_TOGGLE": SetCallback(action, new ActionToggleDelegate(ActionToggle), evt); break;
          case "BUTTON_CB": SetCallback(action, new ButtonCBDelegate(ButtonCB), evt); break;
          case "SPIN_CB": SetCallback(action, new SpinCBDelegate(SpinCB), evt); break;
          case "MAP_CB": SetCallback(action, new MapCBDelegate(MapCB), evt); break;
          case "UNMAP_CB": SetCallback(action, new UnMapCBDelegate(UnMapCB), evt); break;
          case "GETFOCUS_CB": SetCallback(action, new GetFocusCBDelegate(GetFocusCB), evt); break;
          case "KILLFOCUS_CB": SetCallback(action, new KillFocusCBDelegate(KillFocusCB), evt); break;
          case "ENTERWINDOW_CB": SetCallback(action, new EnterWindowCBDelegate(EnterWindowCB), evt); break;
          case "LEAVEWINDOW_CB": SetCallback(action, new LeaveWindowCBDelegate(LeaveWindowCB), evt); break;
          case "K_ANY": SetCallback(action, new KAnyCBDelegate(KAnyCB), evt); break;
          case "HELP_CB": SetCallback(action, new HelpCBDelegate(HelpCB), evt); break;
          case "CARET_CB": SetCallback(action, new CaretCBDelegate(CaretCB), evt); break;
          case "MOTION_CB": SetCallback(action, new MotionCBDelegate(MotionCB), evt); break;
          case "DROPFILES_CB": SetCallback(action, new DropFilesCBDelegate(DropFilesCB), evt); break;
          case "FOCUS_CB": SetCallback(action, new FocusCBDelegate(FocusCB), evt); break;
          case "KEYPRESS_CB": SetCallback(action, new KeyPressCBDelegate(KeyPressCB), evt); break;
          case "RESIZE_CB": SetCallback(action, new ResizeCBDelegate(ResizeCB), evt); break;
          case "SCROLL_CB": SetCallback(action, new ScrollCBDelegate(ScrollCB), evt); break;
          case "WHEEL_CB": SetCallback(action, new WheelCBDelegate(WheelCB), evt); break;
          case "CHANGEVALUE_CB": SetCallback(action, new ChangeValueCBDelegate(ChangeValueCB), evt); break;
          case "TABCHANGE_CB": SetCallback(action, new TabChangeCBDelegate(TabChangeCB), evt); break;
          case "ACTION_LIST": SetCallback(action, new ActionListDelegate(ActionListCB), evt); break;
          case "DBLCLICK_CB": SetCallback(action, new DblClickCBDelegate(DblClickCB), evt); break;
          case "DROPDOWN_CB": SetCallback(action, new DropDownCBDelegate(DropDownCB), evt); break;
          case "EDIT_CB": SetCallback(action, new EditCBDelegate(EditCB), evt); break;
          case "SELECTION_CB": SetCallback(action, new SelectionCBDelegate(SelectionCB), evt); break;
          case "MULTISELECTION_CB": SetCallback(action, new MultiSelectionCBDelegate(MultiSelectionCB), evt); break;
          case "BRANCHOPEN_CB": SetCallback(action, new BranchOpenCBDelegate(BranchOpenCB), evt); break;
          case "BRANCHCLOSE_CB": SetCallback(action, new BranchCloseCBDelegate(BranchCloseCB), evt); break;
          case "EXECUTELEAF_CB": SetCallback(action, new ExecuteLeafCBDelegate(ExecuteLeafCB), evt); break;
          case "RENAMENODE_CB": SetCallback(action, new RenameNodeCBDelegate(RenameNodeCB), evt); break;
          case "SHOWRENAME_CB": SetCallback(action, new ShowRenameCBDelegate(ShowRenameCB), evt); break;
          case "RENAME_CB": SetCallback(action, new RenameCBDelegate(RenameCB), evt); break;
          case "DRAGDROP_CB": SetCallback(action, new DragDropCBDelegate(DragDropCB), evt); break;
          case "RIGHTCLICK_CB": SetCallback(action, new RightClickCBDelegate(RightClickCB), evt); break;
          case "CLOSE_CB": SetCallback(action, new CloseCBDelegate(CloseCB), evt); break;
          case "SHOW_CB": SetCallback(action, new ShowCBDelegate(ShowCB), evt); break;
          case "TRAYCLICK_CB": SetCallback(action, new TrayClickCBDelegate(TrayClickCB), evt); break;
          case "FILE_CB": SetCallback(action, new FileCBDelegate(FileCB), evt); break;
          case "OPEN_CB": SetCallback(action, new OpenCBDelegate(OpenCB), evt); break;
          case "MENUCLOSE_CB": SetCallback(action, new MenuCloseCBDelegate(MenuCloseCB), evt); break;
          case "ACTION_ITEM": SetCallback(action, new ActionItemDelegate(ActionItem), evt); break;
          case "HIGHLIGHT_CB": SetCallback(action, new HighlightCBDelegate(HighlightCB), evt); break;
          default:
            throw new Exception("Invalid/unknown event identitifier: " + action);
        }
        // usercallbacks[action] = new CallbackPair(evt,null);
      }
    }

    internal EventCallback Fetch(string str)
    {
      CallbackPair res;
      if (usercallbacks.TryGetValue(str, out res))
        return res.UserCallback;
      return null;
    }


    int TryCall(string func, CallbackData e)
    {
      CallbackPair callback;
      if (usercallbacks.TryGetValue(func, out callback))
      {
        e.EventName = UnDecorateAction(func);
        callback.UserCallback(e);
        return (int)e.Result;
      }
      return (int)CallbackRes.Default;
    }


    int ActionButton(IntPtr sender, int button, int press, int x, int y)
    {
      return TryCall(
          "ACTION_BUTTON",
          new CallbackData(sender)
      );
    }

    int ButtonCB(IntPtr sender, int button, int press, int x, int y)
    {
      return TryCall(
          "BUTTON_CB",
          new CallbackData(sender) { X = x, Y = y, Active = press == 0 ? false : true, Value = button - 48 }
      );
    }

    int SpinCB(IntPtr sender, int inc)
    {
      return TryCall(
          "SPIN_CB",
          new CallbackData(sender) { Value = inc }
      );
    }

    int MapCB(IntPtr sender)
    {
      return TryCall(
          "MAP_CB",
          new CallbackData(sender) { }
      );
    }

    int UnMapCB(IntPtr sender)
    {
      return TryCall(
          "UNMAP_CB",
          new CallbackData(sender) { }
      );
    }

    int GetFocusCB(IntPtr sender)
    {
      return TryCall(
          "GETFOCUS_CB",
          new CallbackData(sender) { }
      );
    }

    int KillFocusCB(IntPtr sender)
    {
      return TryCall(
          "KILLFOCUS_CB",
          new CallbackData(sender) { }
      );
    }

    int EnterWindowCB(IntPtr sender)
    {
      return TryCall(
          "ENTERWINDOW_CB",
          new CallbackData(sender) { }
      );
    }

    int LeaveWindowCB(IntPtr sender)
    {
      return TryCall(
          "LEAVEWINDOW_CB",
          new CallbackData(sender) { }
      );
    }

    int KAnyCB(IntPtr sender, int key)
    {
      return TryCall(
          "K_ANY",
          new CallbackData(sender) { Key = (Key)key }
      );
    }

    int HelpCB(IntPtr sender)
    {
      return TryCall(
          "HELP_CB",
          new CallbackData(sender) { }
      );
    }

    int CaretCB(IntPtr sender, int lin, int col, int pos)
    {
      return TryCall(
          "CARET_CB",
          new CallbackData(sender) { X = lin, Y = col, Value = pos }
      );
    }

    int MotionCB(IntPtr sender, int x, int y, string status)
    {
      return TryCall(
          "MOTION_CB",
          new CallbackData(sender) { X = x, Y = y, Status = new Status(status) }
      );
    }

    int DropFilesCB(IntPtr sender, string filename, int num, int x, int y)
    {
      return TryCall(
          "DROPFILES_CB",
          new CallbackData(sender) { X = x, Y = y, Value = num, Text = filename }
      );
    }


    int ActionText(IntPtr sender, int c, string newvalue)
    {
      CallbackData ed = new CallbackData(sender) { Value = c, Text = newvalue };
      TryCall(
          "ACTION_TEXT",
          ed
      );

      //now , if value has been changed, return this as result,
      //but if result was changed, it wins
      if (ed.Result != CallbackRes.Default)
        return (int)ed.Result;
      else if (ed.Value != c)
        return ed.Value;
      return (int)ed.Result;
    }

    int ActionCanvas(IntPtr sender, float posx, float posy)
    {
      return TryCall(
          "ACTION_CANVAS",
          new CallbackData(sender) { PosX = posx, PosY = posy }
      );
    }

    int FocusCB(IntPtr sender, int focus)
    {
      return TryCall(
          "FOCUS_CB",
          new CallbackData(sender) { Active = (focus != 0) }
      );
    }

    int KeyPressCB(IntPtr sender, int c, int press)
    {
      return TryCall(
          "KEYPRESS_CB",
          new CallbackData(sender) { Active = (press != 0), Key = (Key)c }
      );
    }

    int ResizeCB(IntPtr sender, int w, int h)
    {
      return TryCall(
          "RESIZE_CB",
          new CallbackData(sender) { X = w, Y = h }
      );
    }

    int ScrollCB(IntPtr sender, int op, float posx, float posy)
    {
      //TODO: maybe op should be an enum instead
      return TryCall(
          "SCROLL_CB",
          new CallbackData(sender) { PosX = posx, PosY = posy, Value = op }
      );
    }

    int WheelCB(IntPtr sender, float delta, int x, int y, string status)
    {
      //for now, we use integer delta for wheel function, all devices i know of this is enough
      int val = (int)Math.Round(delta);
      return TryCall(
          "WHEEL_CB",
          new CallbackData(sender) { Value = val, X = x, Y = y, Status = new Status(status) }
      );
    }

    int ActionToggle(IntPtr sender, int state)
    {
      //for now, we use integer delta for wheel function, all devices i know of this is enough

      return TryCall(
          "ACTION_TOGGLE",
          new CallbackData(sender) { Value = state, Active = state != 0 }
      );
    }


    int ChangeValueCB(IntPtr sender, double val)
    {
      return TryCall(
          "CHANGEVALUE_CB",
          new CallbackData(sender) { Pos = val }
      );

    }

    int TabChangeCB(IntPtr sender, IntPtr newtab, IntPtr oldtab)
    {
      return TryCall("TABCHANGE_CB",
          new CallbackData(sender) { OldTab = Control.FindControl(oldtab), NewTab = Control.FindControl(newtab) });

    }

    int ActionListCB(IntPtr sender, string text, int pos, int state)
    {
      bool active = state != 0;
      return TryCall("ACTION_LIST", new CallbackData(sender) { Active = active, Value = pos - 1, Text = text });
    }


    int DblClickCB(IntPtr sender, int pos, string text)
    {
      return TryCall("DBLCLICK_CB", new CallbackData(sender) { Value = pos - 1, Text = text });
    }

    int DropDownCB(IntPtr sender, int state)
    {
      bool active = state != 0;
      return TryCall("DBLCLICK_CB", new CallbackData(sender) { Active = active });
    }

    int EditCB(IntPtr sender, int c, string newvalue)
    {

      CallbackData ed = new CallbackData(sender) { Value = c };
      TryCall(
          "EDIT_CB",
          new CallbackData(sender) { Value = c, Text = newvalue }
      );

      //now , if value has been changed, return this as result,
      //but if result was changed, it wins
      if (ed.Result != CallbackRes.Default)
        return (int)ed.Result;
      else if (ed.Value != c)
        return ed.Value;
      return (int)ed.Result;
    }

    int SelectionCB(IntPtr sender, int id, int status)
    {
      bool active = status != 0;
      return TryCall(
          "SELECTION_CB",
          new CallbackData(sender) { Value = id, Active = active }
      );
    }

    int MultiSelectionCB(IntPtr sender, IntPtr ids, int n)
    {

      int[] vals = new int[n];
      Marshal.Copy(ids, vals, 0, n);

      return TryCall(
          "MULTISELECTION_CB",
          new CallbackData(sender) { Values = vals }
      );
    }

    int BranchOpenCB(IntPtr sender, int id)
    {

      return TryCall(
          "BRANCHOPEN_CB",
          new CallbackData(sender) { Value = id }
      );
    }

    int BranchCloseCB(IntPtr sender, int id)
    {
      return TryCall(
          "BRANCHCLOSE_CB",
          new CallbackData(sender) { Value = id }
      );
    }

    int ExecuteLeafCB(IntPtr sender, int id)
    {
      return TryCall(
          "EXECUTELEAF_CB",
          new CallbackData(sender) { Value = id }
      );
    }

    int RenameNodeCB(IntPtr sender, int id, string name)
    {
      return TryCall(
          "RENAMENODE_CB",
          new CallbackData(sender) { Value = id, Text = name }
      );
    }

    int ShowRenameCB(IntPtr sender, int id)
    {
      return TryCall(
          "SHOWRENAME_CB",
          new CallbackData(sender) { Value = id }
      );
    }


    int RenameCB(IntPtr sender, int id, string name)
    {
      return TryCall(
          "RENAME_CB",
          new CallbackData(sender) { Value = id, Text = name }
      );
    }

    int DragDropCB(IntPtr sender, int drag_id, int drop_id, int isshift, int iscontrol)
    {
      bool s = isshift != 0;
      bool c = iscontrol != 0;
      return TryCall(
          "DRAGDROP_CB",
          new CallbackData(sender) { Values = new int[] { drag_id, drop_id }, Status = new Status(isshift != 0, iscontrol != 0) }
      );
    }

    int RightClickCB(IntPtr sender, int id)
    {
      return TryCall(
          "RIGHTCLICK_CB",
          new CallbackData(sender) { Value = id }
      );
    }

    int CloseCB(IntPtr sender)
    {
      return TryCall(
          "CLOSE_CB",
          new CallbackData(sender) { }
      );
    }

    int ShowCB(IntPtr sender, int state)
    {

      return TryCall(
          "SHOW_CB",
          new CallbackData(sender) { ShowState = (ShowState)state }
      );
    }


    int TrayClickCB(IntPtr sender, int but, int press, int dclick)
    {
      bool active = press != 0;
      bool dc = dclick != 0;

      return TryCall(
          "TRAYCLICK_CB",
          new CallbackData(sender) { Value = but, Active = active, DoubleClick = dc }
      );

    }

    int FileCB(IntPtr sender, string file, string status)
    {
      FileDialogStatus stat;
      switch (status)
      {
        case "INIT": stat = FileDialogStatus.Init; break;
        case "FINISH": stat = FileDialogStatus.Finish; break;
        case "SELECT": stat = FileDialogStatus.Select; break;
        case "OK": stat = FileDialogStatus.Ok; break;
        case "PAINT": stat = FileDialogStatus.Paint; break;
        default: stat = FileDialogStatus.Select; break;
      }

      return TryCall(
          "FILE_CB",
          new CallbackData(sender) { FileDialogStatus = stat, Text = file }
      );
    }

    int OpenCB(IntPtr sender)
    {
      return TryCall(
          "OPEN_CB",
          new CallbackData(sender)
      );
    }

    int MenuCloseCB(IntPtr sender)
    {
      return TryCall(
          "MENUCLOSE_CB",
          new CallbackData(sender)
      );
    }

    int HighlightCB(IntPtr sender)
    {
      return TryCall(
          "HIGHLIGHT_CB",
          new CallbackData(sender)
      );
    }

    int ActionItem(IntPtr sender)
    {
      return TryCall(
          "ACTION_ITEM",
          new CallbackData(sender)
      );
    }

  }





}
